package com.blacktech.dbu.auth.service;

import com.blacktech.dbu.auth.entity.DbuUser;
import com.blacktech.dbu.auth.entity.DbuUserProduct;
import com.blacktech.dbu.auth.repository.UserProductRepository;
import com.blacktech.dbu.auth.repository.UserRepository;
import com.blacktech.dbu.core.dict.PermissionType;
import com.blacktech.dbu.meta.entity.DbuProduct;
import com.blacktech.dbu.meta.repository.ProductRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

/**
 * 用户产品权限管理服务
 *
 * @author Yanyunsong
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserProductService {

    private final UserProductRepository userProductRepository;
    private final UserRepository userRepository;
    private final ProductRepository productRepository;
    private final AuthorizationService authorizationService;

    /**
     * 为用户分配产品权限
     *
     * @param userId          用户ID
     * @param productId       产品ID
     * @param permissionLevel 权限级别 (1:OWNER, 2:COLLABORATOR, 3:REPORTER)
     * @param remark          备注说明
     * @return 权限记录
     */
    @Transactional
    public DbuUserProduct assignPermission(Long userId, Long productId, Integer permissionLevel, String remark) {
        log.info("开始为用户 {} 分配产品 {} 的权限级别: {}", userId, productId, permissionLevel);

        // 验证用户和产品存在
        DbuUser user = userRepository.findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在: " + userId));
        DbuProduct product = productRepository.findById(productId)
                .orElseThrow(() -> new IllegalArgumentException("产品不存在: " + productId));

        // 检查是否已存在权限记录
        Optional<DbuUserProduct> existingPermission = userProductRepository.findByUserIdAndProductId(userId, productId);
        if (existingPermission.isPresent()) {
            throw new IllegalStateException("用户已拥有该产品的权限，请先回收现有权限");
        }

        // 获取当前操作用户
        DbuUser currentUser = authorizationService.getCurrentUser();

        // 创建权限记录
        DbuUserProduct userProduct = new DbuUserProduct();
        userProduct.setUser(user);
        userProduct.setProduct(product);
        userProduct.setPermissionLevel(permissionLevel);
        userProduct.setAssignedBy(currentUser);
        userProduct.setRemark(remark);

        DbuUserProduct savedPermission = userProductRepository.save(userProduct);
        log.info("成功为用户 {} 分配产品 {} 的权限级别: {}", userId, productId, permissionLevel);

        return savedPermission;
    }


    /**
     * 修改用户产品权限
     *
     * @param userId          用户ID
     * @param productId       产品ID
     * @param permissionLevel 新的权限级别 (1:OWNER, 2:COLLABORATOR, 3:REPORTER)
     * @param remark          备注说明
     * @return 更新后的权限记录
     */
    @Transactional
    public DbuUserProduct updatePermission(Long userId, Long productId, Integer permissionLevel, String remark) {
        log.info("开始修改用户 {} 在产品 {} 的权限级别为: {}", userId, productId, permissionLevel);

        DbuUserProduct userProduct = userProductRepository.findByUserIdAndProductId(userId, productId)
                .orElseThrow(() -> new IllegalArgumentException("用户没有该产品的权限"));

        // 获取当前操作用户
        DbuUser currentUser = authorizationService.getCurrentUser();

        userProduct.setPermissionLevel(permissionLevel);
        userProduct.setAssignedBy(currentUser);
        userProduct.setRemark(remark);

        DbuUserProduct updatedPermission = userProductRepository.save(userProduct);
        log.info("成功修改用户 {} 在产品 {} 的权限级别为: {}", userId, productId, permissionLevel);

        return updatedPermission;
    }


    /**
     * 回收用户产品权限
     *
     * @param userId    用户ID
     * @param productId 产品ID
     */
    @Transactional
    public void revokePermission(Long userId, Long productId) {
        log.info("开始回收用户 {} 在产品 {} 的权限", userId, productId);

        DbuUserProduct userProduct = userProductRepository.findByUserIdAndProductId(userId, productId)
                .orElseThrow(() -> new IllegalArgumentException("用户没有该产品的权限"));

        userProductRepository.delete(userProduct);
        log.info("成功回收用户 {} 在产品 {} 的权限", userId, productId);
    }


    /**
     * 获取用户在产品的权限
     *
     * @param userId    用户ID
     * @param productId 产品ID
     * @return 权限记录
     */
    public Optional<DbuUserProduct> getUserProductPermission(Long userId, Long productId) {
        return userProductRepository.findByUserIdAndProductId(userId, productId);
    }

    /**
     * 获取用户所有产品权限
     *
     * @param userId 用户ID
     * @return 权限列表
     */
    public List<DbuUserProduct> getUserPermissions(Long userId) {
        return userProductRepository.findUserPermissions(userId);
    }

    /**
     * 获取产品的所有用户权限
     *
     * @param productId 产品ID
     * @return 权限列表
     */
    public List<DbuUserProduct> getProductPermissions(Long productId) {
        return userProductRepository.findProductPermissions(productId);
    }

    /**
     * 分页查询用户产品权限
     *
     * @param userId          用户ID（可选）
     * @param productId       产品ID（可选）
     * @param permissionLevel 权限级别（可选）
     * @param pageable        分页参数
     * @return 分页结果
     */
    public Page<DbuUserProduct> searchPermissions(Long userId, Long productId, Integer permissionLevel, Pageable pageable) {
        return userProductRepository.findByConditions(userId, productId, permissionLevel, pageable);
    }


    /**
     * 产品创建时，为创建者自动分配OWNER权限
     *
     * @param product   产品实体
     * @param creatorId 创建者ID
     */
    @Transactional
    public void assignOwnerPermission(DbuProduct product, Long creatorId) {
        log.info("为产品创建者 {} 自动分配产品 {} 的OWNER权限", creatorId, product.getId());

        DbuUser creator = userRepository.findById(creatorId)
                .orElseThrow(() -> new IllegalArgumentException("创建者用户不存在: " + creatorId));

        DbuUserProduct userProduct = new DbuUserProduct();
        userProduct.setUser(creator);
        userProduct.setProduct(product);
        userProduct.setPermissionLevel(PermissionType.Level.OWNER);
        userProduct.setAssignedBy(creator);
        userProduct.setRemark("产品创建时自动分配");

        userProductRepository.save(userProduct);
        log.info("成功为产品创建者分配OWNER权限");
    }

    /**
     * 删除产品时，清理相关权限记录
     *
     * @param productId 产品ID
     */
    @Transactional
    public void cleanupProductPermissions(Long productId) {
        log.info("开始清理产品 {} 的所有权限记录", productId);
        userProductRepository.deleteByProductId(productId);
        log.info("成功清理产品 {} 的所有权限记录", productId);
    }

    /**
     * 验证权限分配操作是否合法
     *
     * @param operatorId      操作者ID
     * @param targetUserId    目标用户ID
     * @param productId       产品ID
     * @param permissionLevel 要分配的权限级别
     * @return 是否可以分配
     */
    public boolean canAssignPermission(Long operatorId, Long targetUserId, Long productId, Integer permissionLevel) {
        // 获取操作者在产品的权限
        Optional<DbuUserProduct> operatorPermission = userProductRepository.findByUserIdAndProductId(operatorId, productId);

        // 只有OWNER可以分配权限
        if (operatorPermission.isEmpty() || operatorPermission.get().getPermissionLevel() != PermissionType.Level.OWNER) {
            log.warn("用户 {} 尝试在产品 {} 分配权限，但没有OWNER权限", operatorId, productId);
            return false;
        }

        // 不能给自己分配权限
        if (operatorId.equals(targetUserId)) {
            log.warn("用户 {} 尝试给自己分配产品 {} 的权限", operatorId, productId);
            return false;
        }

        return true;
    }


    /**
     * 获取权限统计信息
     *
     * @param productId 产品ID
     * @return 权限统计
     */
    public PermissionStats getPermissionStats(Long productId) {
        List<DbuUserProduct> permissions = getProductPermissions(productId);

        long ownerCount = permissions.stream()
                .filter(p -> p.getPermissionLevel() != null && p.getPermissionLevel() == PermissionType.Level.OWNER)
                .count();
        long collaboratorCount = permissions.stream()
                .filter(p -> p.getPermissionLevel() != null && p.getPermissionLevel() == PermissionType.Level.COLLABORATOR)
                .count();
        long reporterCount = permissions.stream()
                .filter(p -> p.getPermissionLevel() != null && p.getPermissionLevel() == PermissionType.Level.REPORTER)
                .count();

        return new PermissionStats(ownerCount, collaboratorCount, reporterCount, permissions.size());
    }

    /**
     * 权限统计信息
     */
    public record PermissionStats(long ownerCount, long collaboratorCount, long reporterCount, long totalCount) {
    }
}